package cdu.sl.aichatdemo.utils;


import cdu.sl.aichatdemo.constants.JwtConstants;
import cdu.sl.aichatdemo.pojo.entity.User;
import io.jsonwebtoken.*;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SignatureException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Jwt工具类
 */
@Slf4j
@Component
public class JwtUtil {

    @Value("${jwt.secret}")
    private String secret;

    @Value("${jwt.default-expiration}")
    private Long expiration;

    @Value("${jwt.refresh-token-expiration}")
    private Long refreshExpiration;


    public SecretKey getSecretKey() {
        return Keys.hmacShaKeyFor(io.jsonwebtoken.io.Decoders.BASE64.decode(secret));
    }


    public String generateRefreshToken(User user) {
        // 根据id , 生成一个刷新令牌
        return Jwts.builder()
                .setSubject(user.getId().toString())
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + refreshExpiration))
                .signWith(getSecretKey(), SignatureAlgorithm.HS256)
                .compact();
    }


    /**
     * 生成Token
     */
    public String generateTokenByUser(User user) {
        // 根据User实体信息构造claims
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtConstants.JWT_CLAIMS_EMAIL, user.getEmail());
        claims.put(JwtConstants.JWT_CLAIMS_ID, user.getId());
        claims.put(JwtConstants.JWT_CLAIMS_USERNAME, user.getUsername());
        claims.put(JwtConstants.JWT_CLAIMS_STATUS, user.getStatus());


        return Jwts.builder()
                .setClaims(claims)
                .setSubject(String.valueOf(user.getId()))
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + expiration))
                .signWith(getSecretKey(), SignatureAlgorithm.HS256)
                .compact();
    }


    /**
     * 校验Token合法性
     */
    public Boolean validateToken(String token) {
        try {
            Jwts.parserBuilder()
                    .setSigningKey(getSecretKey())
                    .build()
                    .parseClaimsJws(token);
            return true;
        } catch (SignatureException e) {
            log.info("Invalid JWT signature: {}", e.getMessage());
        } catch (MalformedJwtException e) {
            log.error("Invalid JWT token: {}", e.getMessage());
        } catch (ExpiredJwtException e) {
            log.error("JWT token is expired: {}", e.getMessage());
        } catch (UnsupportedJwtException e) {
            log.error("JWT token is unsupported: {}", e.getMessage());
        } catch (IllegalArgumentException e) {
            log.error("JWT claims string is empty: {}", e.getMessage());
        }
        return false;
    }

    /**
     * 从token中获取用户id
     *
     * @param token token令牌
     * @return 用户id
     */
    public Long getUserIdFromToken(String token) {
        if (getClaimsFromToken(token).getSubject() == null) {
            log.warn("Invalid JWT token: {}", token);
            return null;
        }
        return Long.valueOf(getClaimsFromToken(token).getSubject());
    }

    /**
     * 从token中获取声明
     *
     * @param token token令牌
     * @return 声明
     */
    public Claims getClaimsFromToken(String token) {
        try {
            return Jwts.parserBuilder()
                    .setSigningKey(getSecretKey())
                    .build()
                    .parseClaimsJws(token)
                    .getBody();
        } catch (JwtException e) {
            log.info("Invalid JWT token: {}", e.getMessage());
            return null;
        }
    }


}
